/* * Copyright (C) 2014 BeyondAR * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.beyondar.android.util.location; import android.location.GpsStatus; import android.location.Location; import android.location.LocationListener; import android.location.LocationManager; import com.beyondar.android.world.GeoObject; import com.beyondar.android.world.World; /** * This class provides a helper to get the best location. To do that the * application needs to add the following permissions in the manifest: <br> * * <pre> * android.permission.ACCESS_FINE_LOCATION * android.permission.ACCESS_COARSE_LOCATION * </pre> * * Remember that you also can use the Location utility in the Google Services. <br> * <br> * Here is a small example how to use {@link BeyondarLocationManager}: <br> * * <pre> * <code> * void onCreate(Bundle savedInstanceState){ * BeyondarLocationManager.setLocationManager((LocationManager) this.getSystemService(Context.LOCATION_SERVICE)); * BeyondarLocationManager.addGeoObjectLocationUpdate(beyondarObject); * // You also can register a World or a LocationListener * // Don't forget to remove the object that you register * } * void onResume(){ * BeyondarLocationManager.enable(); * } * * void onPause(){ * BeyondarLocationManager.disable(); * } * </code> * </pre> */ public class BeyondarLocationManager { public final static int MAX_TIME_GPS_FIX = 20000; private BeyondarLocationManager() { } private static enum BeyondarLocationManagerSingleton { INSTANCE; private LocationManager mLocationManager; private BeyondarLocation mLocationListener; private BeyondarGpsListener mGpsListener; private boolean mIsEnabled; private boolean mGpsFix; private BeyondarLocationManagerSingleton() { mLocationListener = new BeyondarLocation(); mGpsListener = new BeyondarGpsListener(); mIsEnabled = false; mGpsFix = false; } public void setLocationManager(LocationManager locationManager) { mLocationManager = locationManager; } public void enable() { if (mLocationManager == null) { mIsEnabled = false; return; } if (!mIsEnabled) { Location lastGpsLocation = mLocationManager .getLastKnownLocation(LocationManager.GPS_PROVIDER); Location lastNetworkLocation = mLocationManager .getLastKnownLocation(LocationManager.NETWORK_PROVIDER); if (LocationUtils.isBetterLocation(lastNetworkLocation, lastGpsLocation)) { mLocationListener.setLastKnowLocation(lastNetworkLocation); } else { mLocationListener.setLastKnowLocation(lastGpsLocation); } } registerLocationListener(mLocationListener, mGpsListener); mIsEnabled = true; } public void registerLocationListener(LocationListener locationListener, GpsStatus.Listener gpsListener) { if (mLocationManager.getAllProviders().contains(LocationManager.GPS_PROVIDER)) { mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener); mLocationManager.addGpsStatusListener(gpsListener); } if (mLocationManager.getAllProviders().contains(LocationManager.NETWORK_PROVIDER)) { mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener); } } public void disable() { mIsEnabled = false; mGpsFix = false; if (mLocationManager != null) { mLocationManager.removeUpdates(mLocationListener); } } public boolean isEnabled() { return mIsEnabled; } public boolean gpsFix() { return mGpsFix; } private class BeyondarGpsListener implements GpsStatus.Listener { public void onGpsStatusChanged(int event) { switch (event) { case GpsStatus.GPS_EVENT_SATELLITE_STATUS: if (mLocationListener.getLastGpsLocation() != null) { if ((System.currentTimeMillis() - mLocationListener.getLastGpsLocation().getTime()) < MAX_TIME_GPS_FIX) { if (!mGpsFix) mGpsFix = true; } else { if (mGpsFix) { enable(); } mGpsFix = false; } } break; case GpsStatus.GPS_EVENT_FIRST_FIX: mGpsFix = true; break; case GpsStatus.GPS_EVENT_STARTED: break; case GpsStatus.GPS_EVENT_STOPPED: mGpsFix = false; break; } } } } /** * Set the {@link LocationManager} needed by the helper to be able to take * care of the location. * * @param locationManager */ public static void setLocationManager(LocationManager locationManager) { // TODO: Check what happens if an other locationManager is set BeyondarLocationManagerSingleton.INSTANCE.setLocationManager(locationManager); } /** * Add a {@link com.beyondar.android.world.GeoObject GeoObject} that will be * updated with the user location. * * @param geoObject */ public static void addGeoObjectLocationUpdate(GeoObject geoObject) { BeyondarLocationManagerSingleton.INSTANCE.mLocationListener.addGeoObjectLocationUpdate(geoObject); } /** * Remove the specified {@link com.beyondar.android.world.GeoObject * GeoObject} to don't get any update about the user location. * * @param geoObject */ public static void removeGeoObjectLocationUpdate(GeoObject geoObject) { BeyondarLocationManagerSingleton.INSTANCE.mLocationListener.removeGeoObjectLocationUpdate(geoObject); } /** * Remove all the {@link com.beyondar.android.world.GeoObject GeoObject} to * get the location updates. */ public static void removeAllGeoObjectsUpdates() { BeyondarLocationManagerSingleton.INSTANCE.mLocationListener.removeAllGeoObjectsUpdates(); } /** * Add a {@link World} object that will be updated with the user location. * * @param world */ public static void addWorldLocationUpdate(World world) { BeyondarLocationManagerSingleton.INSTANCE.mLocationListener.addWorldLocationUpdate(world); } /** * Remove the specified {@link World} to don't get any update about the user * location. * * @param world */ public static void removeWorldLocationUpdate(World world) { BeyondarLocationManagerSingleton.INSTANCE.mLocationListener.removeWorldLocationUpdate(world); } /** * Remove all the {@link World} to get the location updates. */ public static void removeAllWorldsUpdates() { BeyondarLocationManagerSingleton.INSTANCE.mLocationListener.removeAllWorldsUpdates(); } /** * Add a {@link LocationListener} object that will be updated with the user * location. * * @param locationListener */ public static void addLocationListener(LocationListener locationListener) { BeyondarLocationManagerSingleton.INSTANCE.mLocationListener.addLocationListener(locationListener); } /** * Remove the specified {@link LocationListener} to don't get any update * about the user location. * * @param locationListener */ public static void removeLocationListener(LocationListener locationListener) { BeyondarLocationManagerSingleton.INSTANCE.mLocationListener.removeLocationListener(locationListener); } /** * Remove all the {@link LocationListener} to get the location updates. */ public static void removeAllLocationListener() { BeyondarLocationManagerSingleton.INSTANCE.mLocationListener.removeAllLocationListener(); } /** * Enable the location services for the helper. Once it will be enabled it * will start consuming battery. */ public static void enable() { BeyondarLocationManagerSingleton.INSTANCE.enable(); } /** * Disable the location services for the helper. If the location is not * needed use this method in order to save battery. */ public static void disable() { BeyondarLocationManagerSingleton.INSTANCE.disable(); } /** * Check if location is enabled or not. * * @return */ public static boolean isEnabled() { return BeyondarLocationManagerSingleton.INSTANCE.isEnabled(); } /** * Check if the satellites are giving a correct location. * * @return */ public static boolean gpsFix() { return BeyondarLocationManagerSingleton.INSTANCE.gpsFix(); } }